﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;


namespace CarlosMisfortune.view
{
    //stolen from Lyria!
    class Input
    {
        public struct InputStatus
        {
            public bool Down;
            public bool JustPressed;
        }

        #region Enums
        public enum KeyboardKey
        {
            A,
            Add,
            B,
            C,
            D,
            Down,
            Delete,
            E,
            Enter,
            F,
            F1,
            F2,
            F3,
            F4,
            F12,
            F6,
            F9,
            G,
            H,
            I,
            J,
            K,
            L,
            Left,
            LeftShift,
            M,
            N,
            NumPad1,
            NumPad2,
            NumPad3,
            NumPad4,
            NumPad5,
            NumPad9,
            O,
            OemComma,
            P,
            Q,
            R,
            Right,
            RightControl,
            RightShift,
            S,
            Subtract,
            Space,
            T,
            Tab,
            U,
            Up,
            V,
            W,
            X,
            Y,
            Z,            
        }

        public enum GamePadButton
        {
            A,
            B,
            Back,
            BigButton,
            DPadDown,
            DPadLeft,
            DPadRight,
            DPadUp,
            LeftShoulder,
            LeftStick,
            LeftThumbstickDown,
            LeftThumbstickLeft,
            LeftThumbstickRight,
            LeftThumbstickUp,
            LeftTrigger,
            RightShoulder,
            RightStick,
            RightThumbstickDown,
            RightThumbstickLeft,
            RightThumbstickRight,
            RightThumbstickUp,
            RightTrigger,
            Start,
            X,
            Y
        }
        #endregion

        #region Fields
        PlayerIndex m_playerIndex;

        GamePadState m_gamePadState;
        GamePadState m_previousGamePadState;

        KeyboardState m_keyboardState;
        KeyboardState m_previousKeyboardState;


        MouseState m_mouseState;
        MouseState m_previousMouseState;

        private int m_invertX;
        private int m_invertY;
        private bool m_holdShoulder = true;
        #endregion

        #region Properties
        public int InvertX
        {
            get { return m_invertX; }
            set { m_invertX = value; }
        }

        public int InvertY
        {
            get { return m_invertY; }
            set { m_invertY = value; }
        }

        public bool HoldShoulder
        {
            get { return m_holdShoulder; }
            set { m_holdShoulder = value; }
        }
        #endregion

        #region Constructor(s)
        public Input(PlayerIndex a_playerIndex)
        {
            m_playerIndex = a_playerIndex;
            m_invertX = -1;
            m_invertY = 1;
        }
        #endregion

        #region Methods
        public void Update()
        {
            m_previousGamePadState = m_gamePadState;
            m_gamePadState = GamePad.GetState(m_playerIndex);

            m_previousKeyboardState = m_keyboardState;
            m_keyboardState = Keyboard.GetState();

            m_previousMouseState = m_mouseState;
            m_mouseState = Mouse.GetState();
        }

        public bool GamePadIsConnected()
        {
            if (m_gamePadState.IsConnected)
            {
                return true;
            }

            return false;
        }

        #region GamePad
        public float GetLeftTrigger()
        {
            return m_gamePadState.Triggers.Left;
        }

        public float GetRightTrigger()
        {
            return m_gamePadState.Triggers.Right;
        }

        public Vector2 GetLeftThumbStick()
        {
            return m_gamePadState.ThumbSticks.Left;
        }

        public Vector2 GetRightThumbStick()
        {
            return m_gamePadState.ThumbSticks.Right;
        }

        public InputStatus GetButtonStatus(GamePadButton a_button)
        {
            switch (a_button)
            {
                case GamePadButton.A:
                    return CheckButtonStatus(Buttons.A);
                case GamePadButton.B:
                    return CheckButtonStatus(Buttons.B);
                case GamePadButton.Back:
                    return CheckButtonStatus(Buttons.Back);
                case GamePadButton.BigButton:
                    return CheckButtonStatus(Buttons.BigButton);
                case GamePadButton.DPadDown:
                    return CheckButtonStatus(Buttons.DPadDown);
                case GamePadButton.DPadLeft:
                    return CheckButtonStatus(Buttons.DPadLeft);
                case GamePadButton.DPadRight:
                    return CheckButtonStatus(Buttons.DPadRight);
                case GamePadButton.DPadUp:
                    return CheckButtonStatus(Buttons.DPadUp);
                case GamePadButton.LeftShoulder:
                    return CheckButtonStatus(Buttons.LeftShoulder);
                case GamePadButton.LeftStick:
                    return CheckButtonStatus(Buttons.LeftStick);
                case GamePadButton.LeftThumbstickDown:
                    return CheckButtonStatus(Buttons.LeftThumbstickDown);
                case GamePadButton.LeftThumbstickLeft:
                    return CheckButtonStatus(Buttons.LeftThumbstickLeft);
                case GamePadButton.LeftThumbstickRight:
                    return CheckButtonStatus(Buttons.LeftThumbstickRight);
                case GamePadButton.LeftThumbstickUp:
                    return CheckButtonStatus(Buttons.LeftThumbstickUp);
                case GamePadButton.LeftTrigger:
                    return CheckButtonStatus(Buttons.LeftTrigger);
                case GamePadButton.RightShoulder:
                    return CheckButtonStatus(Buttons.RightShoulder);
                case GamePadButton.RightStick:
                    return CheckButtonStatus(Buttons.RightStick);
                case GamePadButton.RightThumbstickDown:
                    return CheckButtonStatus(Buttons.RightThumbstickDown);
                case GamePadButton.RightThumbstickLeft:
                    return CheckButtonStatus(Buttons.RightThumbstickLeft);
                case GamePadButton.RightThumbstickRight:
                    return CheckButtonStatus(Buttons.RightThumbstickRight);
                case GamePadButton.RightThumbstickUp:
                    return CheckButtonStatus(Buttons.RightThumbstickUp);
                case GamePadButton.RightTrigger:
                    return CheckButtonStatus(Buttons.RightTrigger);
                case GamePadButton.Start:
                    return CheckButtonStatus(Buttons.Start);
                case GamePadButton.X:
                    return CheckButtonStatus(Buttons.X);
                case GamePadButton.Y:
                    return CheckButtonStatus(Buttons.Y);
                default:
                    InputStatus status;
                    status.Down = false;
                    status.JustPressed = false;
                    return status;
            }
        }

        private InputStatus CheckButtonStatus(Buttons a_button)
        {
            InputStatus status;

            status.Down = m_gamePadState.IsButtonDown(a_button);
            status.JustPressed = status.Down && m_previousGamePadState.IsButtonUp(a_button);

            return status;
        }
        #endregion

        #region Keyboard
        public InputStatus GetKeyStatus(KeyboardKey a_key)
        {
            switch (a_key)
            {
                case KeyboardKey.A:
                    return CheckKeyStatus(Keys.A);
                case KeyboardKey.Add:
                    return CheckKeyStatus(Keys.Add);
                case KeyboardKey.B:
                    return CheckKeyStatus(Keys.B);
                case KeyboardKey.C:
                    return CheckKeyStatus(Keys.C);
                case KeyboardKey.D:
                    return CheckKeyStatus(Keys.D);
                case KeyboardKey.Delete:
                    return CheckKeyStatus(Keys.Delete);
                case KeyboardKey.Down:
                    return CheckKeyStatus(Keys.Down);
                case KeyboardKey.E:
                    return CheckKeyStatus(Keys.E);
                case KeyboardKey.Enter:
                    return CheckKeyStatus(Keys.Enter);
                case KeyboardKey.F:
                    return CheckKeyStatus(Keys.F);
                case KeyboardKey.F1:
                    return CheckKeyStatus(Keys.F1);
                case KeyboardKey.F2:
                    return CheckKeyStatus(Keys.F2);
                case KeyboardKey.F3:
                    return CheckKeyStatus(Keys.F3);
                case KeyboardKey.F4:
                    return CheckKeyStatus(Keys.F4);
                case KeyboardKey.F12:
                    return CheckKeyStatus(Keys.F12);
                case KeyboardKey.F6:
                    return CheckKeyStatus(Keys.F6);
                case KeyboardKey.F9:
                    return CheckKeyStatus(Keys.F9);
                case KeyboardKey.G:
                    return CheckKeyStatus(Keys.G);
                case KeyboardKey.H:
                    return CheckKeyStatus(Keys.H);
                case KeyboardKey.I:
                    return CheckKeyStatus(Keys.I);
                case KeyboardKey.J:
                    return CheckKeyStatus(Keys.J);
                case KeyboardKey.K:
                    return CheckKeyStatus(Keys.K);
                case KeyboardKey.L:
                    return CheckKeyStatus(Keys.L);
                case KeyboardKey.Left:
                    return CheckKeyStatus(Keys.Left);
                case KeyboardKey.LeftShift:
                    return CheckKeyStatus(Keys.LeftShift);
                case KeyboardKey.M:
                    return CheckKeyStatus(Keys.M);
                case KeyboardKey.N:
                    return CheckKeyStatus(Keys.N);
                case KeyboardKey.NumPad1:
                    return CheckKeyStatus(Keys.NumPad1);
                case KeyboardKey.NumPad2:
                    return CheckKeyStatus(Keys.NumPad2);
                case KeyboardKey.NumPad3:
                    return CheckKeyStatus(Keys.NumPad3);
                case KeyboardKey.NumPad4:
                    return CheckKeyStatus(Keys.NumPad4);
                case KeyboardKey.NumPad5:
                    return CheckKeyStatus(Keys.NumPad5);
                case KeyboardKey.NumPad9:
                    return CheckKeyStatus(Keys.NumPad9);
                case KeyboardKey.O:
                    return CheckKeyStatus(Keys.O);
                case KeyboardKey.OemComma:
                    return CheckKeyStatus(Keys.OemComma);
                case KeyboardKey.P:
                    return CheckKeyStatus(Keys.P);
                case KeyboardKey.Q:
                    return CheckKeyStatus(Keys.Q);
                case KeyboardKey.R:
                    return CheckKeyStatus(Keys.R);
                case KeyboardKey.Right:
                    return CheckKeyStatus(Keys.Right);
                case KeyboardKey.RightControl:
                    return CheckKeyStatus(Keys.RightControl);
                case KeyboardKey.RightShift:
                    return CheckKeyStatus(Keys.RightShift);
                case KeyboardKey.S:
                    return CheckKeyStatus(Keys.S);
                case KeyboardKey.Space:
                    return CheckKeyStatus(Keys.Space);
                case KeyboardKey.Subtract:
                    return CheckKeyStatus(Keys.Subtract);
                case KeyboardKey.T:
                    return CheckKeyStatus(Keys.T);
                case KeyboardKey.Tab:
                    return CheckKeyStatus(Keys.Tab);
                case KeyboardKey.U:
                    return CheckKeyStatus(Keys.U);
                case KeyboardKey.Up:
                    return CheckKeyStatus(Keys.Up);
                case KeyboardKey.V:
                    return CheckKeyStatus(Keys.V);
                case KeyboardKey.W:
                    return CheckKeyStatus(Keys.W);
                case KeyboardKey.X:
                    return CheckKeyStatus(Keys.X);
                case KeyboardKey.Y:
                    return CheckKeyStatus(Keys.Y);
                case KeyboardKey.Z:
                    return CheckKeyStatus(Keys.Z);
                default:
                    InputStatus status;
                    status.Down = false;
                    status.JustPressed = false;
                    return status;
            }
        }

        private InputStatus CheckKeyStatus(Keys a_key)
        {
            InputStatus status;

            status.Down = m_keyboardState.IsKeyDown(a_key);
            status.JustPressed = status.Down && m_previousKeyboardState.IsKeyUp(a_key);

            return status;
        }
        #endregion

        #region Mouse
        public Point GetMousePosition()
        {
            return new Point(m_mouseState.X, m_mouseState.Y);
        }

        public void SetMousePosition(int a_x, int a_y)
        {
            Mouse.SetPosition(a_x, a_y);
        }

        public bool GetLeftMouseButtonDown()
        {
            if (m_mouseState.LeftButton == ButtonState.Pressed)
            {
                return true;
            }

            return false;
        }

        public bool GetLeftMouseButtonClick()
        {
            if (GetLeftMouseButtonDown() && m_previousMouseState.LeftButton == ButtonState.Released)
            {
                return true;
            }

            return false;
        }

        public bool GetRightMouseButtonDown()
        {
            if (m_mouseState.RightButton == ButtonState.Pressed)
            {
                return true;
            }

            return false;
        }

        public bool GetRightMouseButtonClick()
        {
            if (GetRightMouseButtonDown() && m_previousMouseState.RightButton == ButtonState.Released)
            {
                return true;
            }

            return false;
        }
        #endregion
        #endregion
    }
}
